﻿namespace TestTool.GUI.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Runtime.CompilerServices;
    using System.Text;
    using TestTool.GUI.Data;
    using TestTool.GUI.Utils;
    using TestTool.GUI.Views;
    using TestTool.Tests.Definitions.Data;
    using TestTool.Tests.Definitions.Interfaces;
    using TestTool.Tests.Definitions.Trace;
    using TestTool.Tests.Engine;

    internal class ConformanceTestController : Controller<IConformanceTestView>
    {
        private int _completedTests;
        private DeviceInformation _conformanceTestingInfo;
        private bool _empty;
        private int _failedTests;
        private bool _preliminaryFailed;
        private int _testsCount;
        private bool _testsDefined;
        private bool _testsRunning;

        public event TestTool.GUI.Utils.ManagementServiceProvider.DeviceInformationReceived DeviceInformationReceived;

        public event Action ExitRequested;

        public event Action HaltRequested;

        public event EventHandler<SettingsMissingEventArgs> SettingsMissing;

        public event Action TestsRunRequested;

        public ConformanceTestController(IConformanceTestView view) : base(view)
        {
        }

        public void Clear()
        {
            if (!this._empty && !this._testsRunning)
            {
                base.View.EnableSaveReport(false);
                base.View.EnableGenerateDoc(false);
                base.View.ClearInfo();
                base.View.ClearLog();
                this._empty = true;
            }
        }

        public void CreateDatasheetReport(string fileName)
        {
            this.CreateReport(fileName, new DatasheetReportGenerator());
        }

        public void CreateDoCReport(string fileName)
        {
            this.CreateReport(fileName, new DoCGenerator());
        }

        public void CreateReport(string fileName)
        {
            this.CreateReport(fileName, new PdfReportGenerator());
        }

        private void CreateReport(string fileName, IReportGenerator reportGenerator)
        {
            this.UpdateContext();
            TestLogFull fullTestData = this.GetFullTestData();
            reportGenerator.OnException += new Action<Exception>(this.reportGenerator_OnException);
            reportGenerator.OnReportSaved += new Action(this.reportGenerator_OnReportSaved);
            reportGenerator.CreateReport(fileName, fullTestData);
            reportGenerator.OnException -= new Action<Exception>(this.reportGenerator_OnException);
            reportGenerator.OnReportSaved -= new Action(this.reportGenerator_OnReportSaved);
        }

        public void DisplayDeviceInfo(DeviceInfo info)
        {
            SetupInfo setupInfo = ContextController.GetSetupInfo();
            if (this.DeviceInformationReceived != null)
            {
                this.DeviceInformationReceived(info.Manufacturer, info.Model, info.FirmwareVersion, info.SerialNumber, info.HardwareID);
            }
            setupInfo.DevInfo = info;
        }

        public void Exit()
        {
            if (this.ExitRequested != null)
            {
                this.ExitRequested();
            }
        }

        private TestLogFull GetFullTestData()
        {
            TestLogFull full = new TestLogFull();
            TestTool.GUI.Data.TestLog testLog = ContextController.GetTestLog();
            full.TestResults = testLog.TestResults;
            full.Features = testLog.Features;
            full.InitializationData = testLog.InitializationData;
            full.FeaturesDefinitionLog = testLog.FeaturesDefinitionLog;
            full.DeviceInformation = this._conformanceTestingInfo;
            if (testLog.TestExecutionTime != DateTime.MinValue)
            {
                full.TestExecutionTime = testLog.TestExecutionTime;
            }
            else
            {
                full.TestExecutionTime = DateTime.Now;
            }
            SetupInfo setupInfo = ContextController.GetSetupInfo();
            full.TesterInfo = setupInfo.TesterInfo;
            full.Application = ContextController.GetApplicationInfo();
            full.ProductName = setupInfo.DevInfo.ProductName;
            full.OtherInformation = setupInfo.OtherInfo;
            full.MemberInfo = setupInfo.MemberInfo;
            full.ManagementSettings = ContextController.GetManagementSettings();
            full.DeviceEnvironment = ContextController.GetDeviceEnvironment();
            return full;
        }

        public void Halt()
        {
            if (this.HaltRequested != null)
            {
                this.HaltRequested();
            }
        }

        public void InitializationCompleted(ConformanceInitializationData data)
        {
            if (this._testsRunning)
            {
                this._testsDefined = true;
                this._testsCount = data.TestsSelected.Count;
                base.View.DefineTestsCount(data.TestsSelected.Count);
                this.ReportFeatureDefinitionResult(data);
            }
        }

        public override void LoadSavedContext(SavedContext context)
        {
            SetupInfo setupInfo = context.SetupInfo;
            if (setupInfo != null)
            {
                if (setupInfo.DevInfo != null)
                {
                    base.View.Brand = setupInfo.DevInfo.Manufacturer;
                    base.View.Model = setupInfo.DevInfo.Model;
                    base.View.OnvifProductName = setupInfo.DevInfo.ProductName;
                }
                base.View.OtherInformation = !string.IsNullOrEmpty(setupInfo.OtherInfo) ? setupInfo.OtherInfo.Replace("\n", "\r\n") : string.Empty;
                if (setupInfo.TesterInfo != null)
                {
                    base.View.OperatorName = setupInfo.TesterInfo.Operator;
                    base.View.OrganizationName = setupInfo.TesterInfo.Organization;
                    base.View.OrganizationAddress = !string.IsNullOrEmpty(setupInfo.TesterInfo.Address) ? setupInfo.TesterInfo.Address.Replace("\n", "\r\n") : string.Empty;
                }
                if (setupInfo.MemberInfo != null)
                {
                    base.View.MemberName = setupInfo.MemberInfo.Name;
                    base.View.MemberAddress = setupInfo.MemberInfo.Address;
                }
                ContextController.UpdateSetupInfo(setupInfo);
            }
        }

        public void RaiseSettingsMissing(List<string> settings)
        {
            if (this.SettingsMissing != null)
            {
                SettingsMissingEventArgs e = new SettingsMissingEventArgs {
                    Settings = settings
                };
                this.SettingsMissing(this, e);
            }
        }

        public void ReportFeatureDefinitionResult(ConformanceInitializationData data)
        {
            this._conformanceTestingInfo = data.DeviceInformation;
            this._preliminaryFailed = false;
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("Feature definition process {0} ({1} supported, {2} unsupported, {3} undefined)", new object[] { (data.UndefinedFeatures.Count > 0) ? "FAILED" : "PASSED", data.SupportedFeatures.Count, data.UnsupportedFeatures.Count, data.UndefinedFeatures.Count });
            builder.AppendLine(Environment.NewLine + "Profile Support Preliminary Check:");
            foreach (IProfileDefinition definition in data.SupportedProfiles)
            {
                builder.AppendFormat("   {0} SUPPORTED{1}", definition.Name, Environment.NewLine);
            }
            foreach (IProfileDefinition definition2 in data.UnsupportedProfiles)
            {
                builder.AppendFormat("   {0} NOT SUPPORTED{1}", definition2.Name, Environment.NewLine);
            }
            foreach (IProfileDefinition definition3 in data.FailedProfiles)
            {
                builder.AppendFormat("   {0} FAILED{1}", definition3.Name, Environment.NewLine);
            }
            if ((data.SupportedProfiles.Count == 0) && (data.FailedProfiles.Count == 0))
            {
                this._preliminaryFailed = true;
                builder.AppendLine("No profiles supported, conformance will be FAILED");
            }
            if (data.FailedProfiles.Count > 0)
            {
                this._preliminaryFailed = true;
                builder.AppendLine("Not all profiles claimed are supported, conformance will be FAILED");
            }
            if (data.UndefinedFeatures.Count > 0)
            {
                this._preliminaryFailed = true;
                builder.AppendLine("Not all features were defined, conformance will be FAILED");
            }
            base.View.Log(builder.ToString());
        }

        private void reportGenerator_OnException(Exception ex)
        {
            base.View.ShowError(ex);
        }

        private void reportGenerator_OnReportSaved()
        {
            base.View.ReportDocumentCreationCompleted();
        }

        public void RunAll()
        {
            this._completedTests = 0;
            this._testsDefined = false;
            this._testsCount = 0;
            this._failedTests = 0;
            this._empty = false;
            base.View.ClearLog();
            base.View.EnableSaveReport(false);
            base.View.EnableGenerateDoc(false);
            if (this.TestsRunRequested != null)
            {
                this._testsRunning = true;
                this.TestsRunRequested();
            }
        }

        public void TestCompleted(TestInfo testInfo, TestTool.Tests.Definitions.Trace.TestLog log)
        {
            if (this._testsRunning)
            {
                if (testInfo.ProcessType == ProcessType.Test)
                {
                    this._completedTests++;
                    if (log.TestStatus == TestStatus.Failed)
                    {
                        this._failedTests++;
                    }
                    base.View.EndTest(testInfo.Id, testInfo.Name, log.TestStatus);
                    base.View.ReportProgress(this._completedTests, this._testsCount, this._failedTests);
                }
                else
                {
                    base.View.EndFeatureDefinition(log.TestStatus);
                }
            }
        }

        public void TestStarted(TestInfo testInfo)
        {
            if (this._testsRunning)
            {
                base.View.BeginTest(testInfo);
            }
            else
            {
                this.Clear();
            }
        }

        public void TestSuiteCompleted(bool bCompletedNormally)
        {
            if (this._testsRunning)
            {
                this._testsRunning = false;
                if (this._testsDefined)
                {
                    this._empty = false;
                    base.View.ReportTestSuiteCompleted(!this._preliminaryFailed, this._completedTests - this._failedTests, this._failedTests, bCompletedNormally);
                    if (bCompletedNormally)
                    {
                        base.View.EnableSaveReport(true);
                        base.View.EnableGenerateDoc(true);
                    }
                }
                else
                {
                    base.View.ReportFeatureDefinitionCompleted(bCompletedNormally);
                }
            }
        }

        public override void UpdateContext()
        {
            base.UpdateContext();
            TesterInfo info = new TesterInfo {
                Operator = base.View.OperatorName,
                Organization = base.View.OrganizationName,
                Address = base.View.OrganizationAddress
            };
            DeviceInfo info2 = new DeviceInfo {
                Manufacturer = base.View.Brand,
                Model = base.View.Model,
                ProductName = base.View.OnvifProductName
            };
            MemberInfo info3 = new MemberInfo {
                Address = base.View.MemberAddress,
                Name = base.View.MemberName
            };
            SetupInfo info4 = new SetupInfo {
                DevInfo = info2,
                OtherInfo = base.View.OtherInformation,
                TesterInfo = info,
                MemberInfo = info3
            };
            ContextController.UpdateSetupInfo(info4);
        }

        public bool Running
        {
            get
            {
                return this._testsRunning;
            }
        }
    }
}

